#include "StdAfx.h"
#include "FileLogger.h"

FileLogger::FileLogger()
{
	logs_.clear();
	max_log_ = 0;
}

FileLogger::~FileLogger()
{
}

static bool CreateUpperDirectory(const char* filename)
{
	char drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
	char path[_MAX_PATH];

	_splitpath_s(filename, drive, _MAX_DRIVE, dir, _MAX_DIR, fname,  _MAX_FNAME, ext, _MAX_EXT );
	int len = (int)strlen(dir);

	if(len <= 1) 
		return TRUE;
	dir[len - 1] = '\0';

	sprintf_s(path, _MAX_PATH, "%s%s", drive, dir);
	if(!CreateUpperDirectory(path))
		return FALSE;

	if(!::CreateDirectoryA(path, NULL))
	{
		DWORD error = GetLastError(); 
		switch (error) 
		{
		case ERROR_ALREADY_EXISTS:
			return TRUE;
		default:
			return FALSE;
		}
	}

	return TRUE; 
}

void FileLogger::SetPath(const char* filename)
{
	if(CreateUpperDirectory(filename))
		file_name_ = filename;
}

void FileLogger::SetMaxLog(size_t count)
{
	max_log_ = count;
}

void FileLogger::WriteLine(std::string& line)
{
	SYSTEMTIME st;
	GetLocalTime(&st);

	char temp_file_name_[_MAX_PATH] = "";
	char drive[_MAX_DRIVE] = "", dir[_MAX_DIR] = "", 
		fname[_MAX_FNAME] = "", ext[_MAX_EXT] = "";

	_splitpath_s(file_name_.c_str(), drive, _MAX_DRIVE, dir, _MAX_DIR, 
		fname,  _MAX_FNAME, ext, _MAX_EXT);
	sprintf_s(temp_file_name_, _MAX_PATH, "%s%s%s%04d-%02d-%02d%s",
		drive, dir, fname, st.wYear, st.wMonth, st.wDay, ext);

	HANDLE hFile = CreateFileA(temp_file_name_, GENERIC_WRITE, FILE_SHARE_READ,
		NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
	if(hFile != INVALID_HANDLE_VALUE) 
	{
		DWORD bytes;
		SetFilePointer(hFile, 0, NULL, FILE_END);
		WriteFile(hFile, line.c_str(), line.size(), &bytes, NULL);
		CloseHandle(hFile);
	}
}

void FileLogger::Write(const char* buffer)
{
	critical_section::scoped_lock scoped(lock_);

	SYSTEMTIME st;
	GetLocalTime(&st);
	char datetime_string[32] = "";
	sprintf_s(datetime_string, "%02d:%02d:%02d[%04X] ", st.wHour, st.wMinute, st.wSecond, ::GetCurrentThreadId());

	std::string line = datetime_string;
	line += buffer;
	line += "\r\n";

	if(max_log_ == 0)
	{
		WriteLine(line);
	}
	else
	{
		logs_.push_back(line);
		if(logs_.size() == max_log_)
		{
			for (unsigned i = 0; i < logs_.size(); ++i)
				WriteLine(logs_.at(i));
			logs_.clear();
		}
	}
}

void FileLogger::Flush()
{
	critical_section::scoped_lock scoped(lock_);

	if(!logs_.empty())
	{
		for (unsigned i = 0; i < logs_.size(); ++i)
			WriteLine(logs_.at(i));
		logs_.clear();
	}
}
